package com.lucky.auth_boot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lucky.auth_boot.exception.BusinessException;
import com.lucky.auth_boot.mapper.RolesUserMapper;
import com.lucky.auth_boot.mapper.UserMapper;
import com.lucky.auth_boot.pojo.dto.ChangePasswordDTO;
import com.lucky.auth_boot.pojo.dto.UserDTO;
import com.lucky.auth_boot.pojo.dto.UserLoginDTO;
import com.lucky.auth_boot.pojo.po.RolesUserPO;
import com.lucky.auth_boot.pojo.po.UserPO;
import com.lucky.auth_boot.pojo.vo.UserLoginToken;
import com.lucky.auth_boot.pojo.vo.UserVO;
import com.lucky.auth_boot.service.UserService;
import com.lucky.auth_boot.utils.JwtUtil;
import com.lucky.auth_boot.utils.RedisUtil;
import com.lucky.auth_boot.utils.SnowflakeIdUtil;
import jakarta.annotation.Resource;
import org.springframework.data.domain.Pageable;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.UUID;

@Service
public class UserServiceImpl implements UserService {
    @Resource
    UserMapper userMapper;

    @Resource
    RolesUserMapper rolesUserMapper;

    @Resource
    RedisUtil redisUtil;

    @Resource
    private AuthenticationManagerBuilder authenticationManagerBuilder;

    @Resource
    private PasswordEncoder passwordEncoder;

    @Override
    public UserLoginToken queryUserLogin(UserLoginDTO user) {
        String verifyCode = (String) redisUtil.getValue("VerifyCode:"+ user.getUuid());
        if (verifyCode == null) {
            throw new BusinessException("验证码已过期");
        }
        if (!verifyCode.equalsIgnoreCase(user.getCode())) {
            throw new BusinessException("验证码输入错误");
        }

        if (user.getUsername().isEmpty() || user.getPassword().isEmpty()) {
            throw new BusinessException("账号密码不能为空");
        }

        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword());
        Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);
        SecurityContextHolder.getContext().setAuthentication(authentication);

//        获取用户状态判断是否封禁
        UserDTO userDTO = (UserDTO) authentication.getPrincipal();
        if (userDTO.getStatus() == 0 ){
            throw new BusinessException("该账号已被封禁！");
        }

//        更新登录时间
        UserPO userInfo = new UserPO();
        userInfo.setLastLoginTime(new Date());
        userInfo.setId(userDTO.getId());
        userMapper.updateById(userInfo);

//        生成token存信息到redis
        UserPO userPO = new UserPO();
        userPO.setUid(userDTO.getUid());
        String token = JwtUtil.generateTokenForUser(userPO);
        userDTO.setToken(token);
        userDTO.setPassword(null);
        userDTO.setLastLoginTime(userInfo.getLastLoginTime());
        redisUtil.setValue("AuthorLogin:"+userDTO.getUid(), userDTO);
//        登录成功，清空验证码
        redisUtil.deleteValue("VerifyCode:"+ user.getUuid());
        return new UserLoginToken(token);
    }

    @Transactional
    @Override
    public String addUserRegister(UserPO user) {
//        判空
        if(user.getUsername().isEmpty() || user.getPassword().isEmpty()) {
            throw new BusinessException(100, "非法参数/参数为空");
        }

        QueryWrapper<UserPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", user.getUsername());
        long i = userMapper.selectCount(queryWrapper);
        if(i > 0) {
            throw new BusinessException(409, "用户已存在");
        }

        SnowflakeIdUtil snowFlake = new SnowflakeIdUtil(2, 3);
        long randomNumber18 = snowFlake.nextId(); // 18位唯一id

        try {
            user.setUid(randomNumber18);
            user.setPassword(passwordEncoder.encode(user.getPassword()));
            user.setRegisterTime(new Date());
            user.setLastLoginTime(new Date());
            user.setStatus(1);
            if(user.getNickname() == null || user.getNickname().isEmpty()) {
                user.setNickname("鱼鱼_"+ UUID.randomUUID().toString().replace("-", "").substring(0, 6));
            }
            userMapper.insert(user);

            // 获取ID
            QueryWrapper<UserPO> wrapper = new QueryWrapper<>();
            wrapper.eq("uid", randomNumber18);
            UserPO userPO = userMapper.selectOne(wrapper);

            // 给新用户添加新身份
            RolesUserPO rolesUserPO = new RolesUserPO();
            rolesUserPO.setUserId(userPO.getId());
            rolesUserPO.setRoleId(1);
            rolesUserMapper.insert(rolesUserPO);
        } catch (Exception e) {
            throw new RuntimeException();
        }
        return null;
    }

    @Override
    public Page<UserVO> getUserListPage(Pageable pageable) {
        try {
        Page<UserVO> page = new Page<>();
        return userMapper.getUserListPage(page);
    } catch (Exception e){
        throw new BusinessException("操作失败");
    }
    }

    @Override
    public UserVO getUserOneById(Integer id) {
        try {
            return userMapper.getUserOneById(id);
        } catch (Exception e){
            throw new BusinessException("操作失败");
        }
    }

    @Override
    public Integer putUserStatus(UserDTO userDTO) {
        try {
            UserPO userPO = new UserPO();
            userPO.setId(userDTO.getId());
            userPO.setStatus(userDTO.getStatus());

            return userMapper.updateById(userPO);
        } catch (Exception e){
            throw new BusinessException("操作失败");
        }
    }

    @Override
    public Integer putUserInfo(UserDTO userDTO) {
        try {
            UserPO userPO = new UserPO();
            userPO.setId(userDTO.getId());
            userPO.setNickname(userDTO.getNickname());
            if (!userDTO.getPassword().isEmpty()) {
                userPO.setPassword(passwordEncoder.encode(userDTO.getPassword()));
            }
            userPO.setStatus(userDTO.getStatus());

            int i = userMapper.updateById(userPO);
            if (i > 0 && !userDTO.getPassword().isEmpty()) {
//                如果修改密码则删除登录状态
                UserVO userOneById = userMapper.getUserOneById(userPO.getId());
                redisUtil.deleteValue("AuthorLogin:"+userOneById.getUid());
            }

            return i;
        } catch (Exception e){
            throw new BusinessException("操作失败");
        }
    }

    @Override
    public Integer putChangePassword(ChangePasswordDTO changePasswordDTO) {
        if (changePasswordDTO.getOldPassword().isEmpty() || changePasswordDTO.getNewPassword().isEmpty()) {
            throw new BusinessException("请检查输入值是否正确");
        }
        UserDTO userDTO = (UserDTO) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        QueryWrapper<UserPO> wrapper = new QueryWrapper<>();
        wrapper.eq("id", userDTO.getId());
        wrapper.eq("uid", userDTO.getUid());
        UserPO userPO = userMapper.selectOne(wrapper);
        if (!passwordEncoder.matches(changePasswordDTO.getOldPassword(),userPO.getPassword())) {
            throw new BusinessException("旧密码错误,请输入正确的密码");
        }
        if (!changePasswordDTO.getCheckPassword().equals(changePasswordDTO.getNewPassword())) {
            throw new BusinessException("两次输入的新密码不一样！");
        }
        try {
            userPO.setPassword(passwordEncoder.encode(changePasswordDTO.getNewPassword()));
            int i = userMapper.updateById(userPO);
            if (i > 0 && !changePasswordDTO.getNewPassword().isEmpty()) {
                redisUtil.deleteValue("AuthorLogin:" + userDTO.getUid());
            }
            return i;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Integer putPersonalInfo(UserDTO userDTO) {
        try {
            UserDTO user = (UserDTO) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            UserPO userPO = new UserPO();
            userPO.setId(user.getId());
            userPO.setNickname(userDTO.getNickname());
            return userMapper.updateById(userPO);
        } catch (Exception e){
            throw new BusinessException("操作失败");
        }
    }
}
